package cmd

import (
	"context"
	"lanmon/internal/backend"
	"lanmon/internal/config"

	"github.com/pkg/errors"
	"github.com/spf13/cobra"

	"os"
	"os/signal"
	"syscall"

	log "github.com/sirupsen/logrus"
)

func run(cmd *cobra.Command, args []string) error {
	ctx := context.Background()
	ctx, cancel := context.WithCancel(ctx)
	defer cancel()

	tasks := []func() error{
		printStartMessage,
		setLogLevel,
		setupBackend,
	}

	for _, t := range tasks {
		if err := t(); err != nil {
			log.Fatal(err)
		}
	}

	defer cleanup()

	sigChan := make(chan os.Signal)
	exitChan := make(chan struct{})
	signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
	log.WithField("signal", <-sigChan).Info("signal received")
	go func() {
		log.Warning("stopping app")
		// TODO: handle graceful shutdown?
		exitChan <- struct{}{}
	}()

	select {
	case <-exitChan:
	case s := <-sigChan:
		log.WithField("signal", s).Info("signal received, stopping immediately")
	}

	return nil
}

func cleanup() error {
	log.Info("cleanup app")

	tasks := []func() error {
		cleanupBackend,
	}
	for _, t := range tasks {
		t()
	}

	return nil
}

func printStartMessage() error {
	log.Info("starting app")
	return nil
}

func setLogLevel() error {
	log.SetLevel(log.Level(uint8(config.C.General.LogLevel)))
	return nil
}

func setupBackend() error {
	if err := backend.Setup(&config.C); err != nil {
		return errors.Wrap(err, "setup backend error")
	}
	return nil
}

func cleanupBackend() error {
	return backend.Cleanup(&config.C)
}
